﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
using System.Web;
using Autofac;
using Autofac.Core;
using Autofac.Integration.Wcf;
using Autofac.Integration.Web;

namespace Cloak.Web.Autofac
{
	/// <summary>
	/// A web application composed with an Autofac container
	/// </summary>
	public abstract class AutofacHttpApplication : HttpApplication, IContainerProviderAccessor
	{
		#region IContainerProviderAccessor

		private static IContainerProvider _containerProvider;

		IContainerProvider IContainerProviderAccessor.ContainerProvider
		{
			get { return ContainerProvider; }
		}

		/// <summary>
		/// Gets the provider which enables composition services for this application
		/// </summary>
		protected IContainerProvider ContainerProvider
		{
			get { return _containerProvider; }
			private set { _containerProvider = value; }
		}
		#endregion

		/// <summary>
		/// Composes this application with the specified module
		/// </summary>
		/// <param name="applicationModule">The module which defines the application's composition</param>
		/// <exception cref="System.InvalidOperationException">Thrown if the application has already been composed</exception>
		protected void Compose(IModule applicationModule)
		{
			Contract.Requires(applicationModule != null);

			if(ContainerProvider != null)
			{
				throw new InvalidOperationException(Resources.ApplicationAlreadyComposed);
			}

			var container = BuildContainer(applicationModule);

			SetWebContainer(container);

			SetWcfContainer(container);
		}

		private static IContainer BuildContainer(IModule applicationModule)
		{
			var containerBuilder = new ContainerBuilder();

			containerBuilder.RegisterModule(applicationModule);

			return containerBuilder.Build();
		}

		private void SetWebContainer(IContainer container)
		{
			ContainerProvider = new ContainerProvider(container);
		}

		private static void SetWcfContainer(IContainer container)
		{
			AutofacHostFactory.Container = container;
		}
	}
}